package service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.javassist.expr.NewArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayResponse;
import com.alipay.api.domain.Data;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.GoodsDetail;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import dao.OderItem_dao;
import dao.Oder_dao;
import dao.PayInfo_dao;
import dao.Product_dao;
import dao.Traveler_dao;
import dto.OderDto;
import dto.OderItemDto;
import entity.Oder;
import entity.Oder_Item;
import entity.PayInfo;
import entity.Product;
import entity.Traveler;
import enums.travelenums;
import service.Oder_service;

@Service
public class Oder_service_impl implements Oder_service {
	private static final Logger log=LoggerFactory.getLogger(Oder_service_impl.class);
	
	@Autowired
	private Oder_dao oder_dao;
	
	@Autowired
	private OderItem_dao oderItem_dao;
	
	@Autowired
	private Traveler_dao traveler_dao;
	
	@Autowired
	private Product_dao product_dao;
	
	@Autowired
	private PayInfo_dao payInfo_dao;
	
	private  String time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

    
	@Transactional
	public boolean saveOderAndTraveler(Oder oder,Traveler traveler) throws Exception {
		try {
			boolean boo1=oder_dao.save_oder(oder);			
			boolean boo2=traveler_dao.save_traveler(traveler);
			boolean boo=boo1&&boo2;
			
			return boo;
		} catch (Exception e) {
			log.info("保存订单和旅客信息失败");
			throw e;
		}
		
	}
	@Transactional
	public boolean save_oderItem(Oder_Item oder_Item) throws Exception {
		
		try {
			return oderItem_dao.save_oderItem(oder_Item);
		} catch (Exception e) {
			log.info("保存订单明细失败");
			throw e;
		}
	}
	public JSONObject getQrCodeAndOder(Integer userId,Integer oderId){
		Oder oder= oder_dao.get_oder(userId, oderId);
		if(oder==null){
			log.info("用户没有该订单，返回二维码失败");
			return null;
		}
		JSONObject obj= new JSONObject();
		obj.put("oderId", oder.getOderId());
		
		// (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，
        // 需保证商户系统端不能重复，建议通过数据库sequence生成，
        String outTradeNo = oder.getOderId().toString();

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        String subject = new StringBuffer().append("Travel扫码支付，订单号:").append(outTradeNo).toString();

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = oder.getPayPrice().toString();

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0";

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";

        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
        String body = new StringBuffer().append("订单:").append(outTradeNo).append("购买商品共").append(totalAmount).append("元").toString();

        // 商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";

        // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId("2088100200300400500");

        // 支付超时，定义为120分钟
        String timeoutExpress = "120m";

        // 商品明细列表，需填写购买商品详细信息，
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        List<Oder_Item> oder_Itemslist=oderItem_dao.getByOderIdUserId(oderId, userId);
        for (Oder_Item oder_Item : oder_Itemslist) {
        	 GoodsDetail goods = GoodsDetail.newInstance(oder_Item.getProductId().toString(), oder_Item.getProductName(),(long)(oder_Item.getProductPrice()*100) , oder_Item.getQuantity());
        	 goodsDetailList.add(goods);
        }            
        // 创建扫码支付请求builder，设置请求参数
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
            .setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
            .setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
            .setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
            .setTimeoutExpress(timeoutExpress)
            .setNotifyUrl("http://www.firsttravel.xin/alipay_callback.do")//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
            .setGoodsDetailList(goodsDetailList);
        
        /** 一定要在创建AlipayTradeService之前调用Configs.init()设置默认参数
         *  Configs会读取classpath下的zfbinfo.properties文件配置信息，如果找不到该文件则确认该文件是否在classpath目录
         */
        Configs.init("zfbinfo.properties");

        /** 使用Configs提供的默认参数
         *  AlipayTradeService可以使用单例或者为静态成员对象，不需要反复new
         */
        AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
        
        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                log.info("支付宝预下单成功: )");

                AlipayTradePrecreateResponse response = result.getResponse();
                dumpResponse(response);

                // 需要修改为运行机器上的路径
                /*String filePath = String.format("/Users/sudo/Desktop/qr-%s.png",
                    response.getOutTradeNo());
                log.info("filePath:" + filePath);
                //                ZxingUtils.getQRCodeImge(response.getQrCode(), 256, filePath);
                break;*/
                obj.put("qrcode",response.getQrCode());
                PayInfo payInfo=new PayInfo(userId,oderId,travelenums.ALIPAY.getState(),response.getParams().get("trade_no"),travelenums.AlipayCallBack.ODER_WAIT_BUYER_PAY,response.getQrCode(),time,time);
                payInfo_dao.savePayInfo(payInfo);
                return obj;
            case FAILED:
                log.error("支付宝预下单失败!!!");
                return null;
            case UNKNOWN:
                log.error("系统异常，预下单状态未知!!!");
                return null;
            default:
                log.error("不支持的交易状态，交易返回异常!!!");
                return null;
        }
	}
	
	public boolean QueryOderStatus(Integer oderId){
		Oder oder=oder_dao.get_oderByoderId(oderId);
		if(oder==null){
			log.info("用户没有该订单");
			return false;
		}
		if(oder.getStatus()>=travelenums.SUCCPAY.getState()){
			log.info("用户已成功付款");
			return true;
		}
		return false;
	}
	
	@Transactional
	public boolean update_oder(Oder oder) throws Exception {
		try {
			return oder_dao.update_oder(oder);
		} catch (Exception e) {
			throw e;
		}
	}

	public boolean remove_oder(Integer oderId) {
		
		return oder_dao.remove_oder(oderId);
	}

	public Oder get_oder(Integer userId, Integer oderId) {
		
		return oder_dao.get_oder(userId, oderId);
	}

	public Oder get_oderByoderId(Integer oderId) {
		// TODO Auto-generated method stub
		return oder_dao.get_oderByoderId(oderId);
	}
	public Traveler get_Traveler(Integer userId, Integer oderId) {
		
		return traveler_dao.get_Traveler(userId, oderId);
	}
	
	public List<Oder> oder_list(Integer userId) {
		
		return oder_dao.oder_list(userId);
	}

	public List<Oder_Item> get_oderItemByOderId(Integer oderId) {
		
		return oderItem_dao.get_oderItemByOderId(oderId);
	}

	public List<Oder_Item> oderItems_list(Integer userId) {
		
		return oderItem_dao.oderItems_list(userId);
	}

	public List<Oder_Item> oder_listBystatus(Integer userId, Integer status) {
		List<Oder> listoder=oder_dao.oder_listBystatus(userId, status);
		List<Oder_Item> oderItem_list=new ArrayList<Oder_Item>();
		for (Oder oder : listoder) {
			Integer oderId=oder.getOderId();
			List<Oder_Item> listitem=oderItem_dao.get_oderItemByOderId(oderId);
			oderItem_list.addAll(listitem);			
		}
		return  oderItem_list;
	}
	
	// 简单打印应答
    private void dumpResponse(AlipayResponse response) {
        if (response != null) {
            log.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
            if (StringUtils.isNotEmpty(response.getSubCode())) {
                log.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
                    response.getSubMsg()));
            }
            log.info("body:" + response.getBody());
        }
    }
    public String alipaycallback(Map<String, String> Params){
    	Integer oderId=Integer.parseInt(Params.get("out_trade_no"));
    	String tradeNo=Params.get("trade_no");	//支付宝交易号
    	String tradeStatus=Params.get("trade_status");
    	Oder oder=oder_dao.get_oderByoderId(oderId);
    	if (oder==null) {
			log.info("用户没有该订单，回调忽略");
			return "用户没有该订单，回调忽略";
		}
    	if (oder.getStatus()>=travelenums.SUCCPAY.getState()) {
			log.info("支付宝重复回调调用");
			return "支付宝重复回调调用";
		}
    	if (travelenums.AlipayCallBack.ODER_TRADE_SUCCESS.equals(tradeStatus)) {
    		oder.setUpdateTime(Params.get("gmt_payment"));
    		oder.setPayTime(Params.get("gmt_payment"));
			oder.setStatus(travelenums.SUCCPAY.getState());
			oder_dao.update_oder(oder);
			
			List<Oder_Item> itemlist=oderItem_dao.get_oderItemByOderId(oderId);
			for (Oder_Item oder_Item : itemlist) {
				Integer productId=oder_Item.getProductId();
				Integer quantity=oder_Item.getQuantity();
				Product productdetail=product_dao.getproByid(productId);
				if(productdetail!=null){
					productdetail.setStock(productdetail.getStock()-quantity);
					product_dao.updateProduct(productdetail);
				}else{
					log.info("订单中没有该商品");
					return "订单中没有该商品";
				}
			}
			log.info("更新订单状态,产品库存.....");
		}
    	PayInfo payInfo=new PayInfo(oder.getUserId(),oderId,tradeNo,tradeStatus,time);
    	payInfo_dao.updatePayInfo(payInfo);
    	return "succ";
    }
	@Override
	public List<Oder> alloder() {

		return oder_dao.alloder();
	}
	
	@Override
	public List<Oder_Item> allOderItem() {
		// TODO Auto-generated method stub
		return oderItem_dao.allOderItem();
	}
	
	@Override
	public List<OderDto> oderDtoList() {
		List<OderDto> oderDtoList=new ArrayList<OderDto>();
		List<Oder> oderlist=oder_dao.alloder();
		for (Oder oder : oderlist) {
			OderDto oderDto=new OderDto();
			Traveler traveler=traveler_dao.get_Traveler(oder.getUserId(), oder.getOderId());
			
			oderDto.setStatus(travelenums.stateOf(oder.getStatus()).getInfo());
			oderDto.setOder(oder);
			oderDto.setTraveler(traveler);
			
			oderDtoList.add(oderDto);			
		}
		return oderDtoList;
	}
	@Override
	public  List<OderDto> getOderDtoByOderId(Integer oderId) {
		List<OderDto> oderDtoList=new ArrayList<OderDto>();
		Oder oder=oder_dao.get_oderByoderId(oderId);
		
			OderDto oderDto=new OderDto();
			Traveler traveler=traveler_dao.get_Traveler(oder.getUserId(), oder.getOderId());			
			oderDto.setStatus(travelenums.stateOf(oder.getStatus()).getInfo());
			oderDto.setOder(oder);
			oderDto.setTraveler(traveler);
			
			oderDtoList.add(oderDto);			
		
		return oderDtoList;
	}
	
	
	@Override
	public OderItemDto oderItemDtoByOderId(Integer oderId) {
		Oder oder=oder_dao.get_oderByoderId(oderId);		
		List<Oder_Item> oderItemList=oderItem_dao.get_oderItemByOderId(oderId);
		Traveler traveler=traveler_dao.get_Traveler(oder.getUserId(), oderId);
		
		OderItemDto oderItemDto=new OderItemDto(oder,oderItemList,traveler,travelenums.stateOf(oder.getStatus()).getInfo(),travelenums.stateOf(oder.getPayType()).getInfo());
		
		return oderItemDto;
	}
	@Override
	public PayInfo getPayInfoByOderId(Integer userId,Integer oderId) {
		
		return payInfo_dao.getPayInfoByOderId(userId, oderId);
	}
	
	
	
	
}
